﻿'use strict';
var debug = require('debug');
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var moment = require('moment');
const fs = require('fs');
var cookieParser = require('cookie-parser');
const querystring = require('querystring');
var bodyParser = require('body-parser');
var ejs = require('ejs');
const onvif = require('node-onvif');
var app = express();

var server = require('http').createServer(app)


app.set('views', path.join(__dirname, 'views'));
app.engine('html', ejs.__express);
app.set('view engine', 'html');




app.use(logger('dev'));
app.use(bodyParser.json({ limit: "200mb", type: 'application/json' }));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use("/uploads", express.static(path.join(__dirname, 'uploads')));



Array.prototype.remove = function (val) {
    var index = this.indexOf(val);
    if (index > -1) {
        this.splice(index, 1);
    }
};


app.all('*', function (req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With");
    res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
    res.header("Access-Control-Allow-Headers", "Content-Type,Access-Token,x-access-token");
    res.header("X-Powered-By", ' 3.2.1')
    if (req.method == "OPTIONS") res.send(200);
    else next();
});


app.get('/test', function (req, res) {


    res.send("success");
});

function calculateAngles(ptzStatus) {
    const panNormalized = parseFloat(ptzStatus.Position.PanTilt.$.x);
    const tiltNormalized = parseFloat(ptzStatus.Position.PanTilt.$.y);

    // 如果设备 Pan+ 为向左旋转（西），则取反
    const panAngle = -panNormalized * 180;
    const tiltAngle = tiltNormalized * 180;

    console.log(`计算得到的 Pan 角度: ${panAngle.toFixed(2)}°, Tilt 角度: ${tiltAngle.toFixed(2)}°`);
    return { panAngle, tiltAngle };
}

// 将 Pan 角度映射到主要方向（八个方向）
function getCardinalDirection(angle) {
    // 标准化角度到 0-360 度
    let dir = angle % 360;
    if (dir < 0) dir += 360;

    console.log(`标准化后的 Pan 角度: ${dir.toFixed(2)}°`);

    // 定义八个方向及其对应的角度范围
    const directions = [
        { name: '北', start: 337.5, end: 22.5 },
        { name: '东北', start: 22.5, end: 67.5 },
        { name: '东', start: 67.5, end: 112.5 },
        { name: '东南', start: 112.5, end: 157.5 },
        { name: '南', start: 157.5, end: 202.5 },
        { name: '西南', start: 202.5, end: 247.5 },
        { name: '西', start: 247.5, end: 292.5 },
        { name: '西北', start: 292.5, end: 337.5 }
    ];

    for (let d of directions) {
        if (d.start <= d.end) {
            if (dir >= d.start && dir < d.end) return d.name;
        } else {
            if (dir >= d.start || dir < d.end) return d.name;
        }
    }

    return '未知';
}

// 结合 Pan 和 Tilt 角度提供详细的方向描述
function getDetailedDirection(panAngle, tiltAngle) {
    const cardinal = getCardinalDirection(panAngle);

    if (tiltAngle > 30) { // 假设向上倾斜超过30度
        return `${cardinal}偏上`;
    } else if (tiltAngle < -30) { // 假设向下倾斜超过30度
        return `${cardinal}偏下`;
    } else {
        return cardinal;
    }
}


app.post('/ptz', function (req, res) {


    let device = new onvif.OnvifDevice({
        xaddr: 'http://192.168.0.183:80/onvif/device_service',
        user: 'admin',
        pass: 'hkyjx1024'
    });

    // 初始化设备连接
    device.init()
        .then(async () => {
            console.log('设备初始化成功');

            // 获取 PTZ 状态
            let params = { 'ProfileToken': 'Profile_1' };
            device.services.ptz.getStatus(params).then((result) => {
                console.log(JSON.stringify(result['data'], null, '  '));
                fs.writeFileSync("a.txt", JSON.stringify(result['data']));

                const onvifResponse = result.data;
                const angles = calculateAngles(onvifResponse.GetStatusResponse.PTZStatus);
                console.log(`当前云台角度 - Pan: ${angles.panAngle.toFixed(2)}°, Tilt: ${angles.tiltAngle.toFixed(2)}°`);

                const cardinalDirection = getCardinalDirection(angles.panAngle);
                const detailedDirection = getDetailedDirection(angles.panAngle, angles.tiltAngle);

                console.log(`当前方向: ${cardinalDirection}`);
                console.log(`当前详细方向: ${detailedDirection}`);

            }).catch((error) => {
                console.error(error);
            });

            let params1 = {
                'ProfileToken': 'Profile_1',
                'Protocol': 'UDP',
            };

            device.services.media.getStreamUri(params1).then((result) => {
                console.log("流信息")
                console.log(JSON.stringify(result['data'], null, '  '));
            }).catch((error) => {
                console.error(error);
            });

            let params2 = {
                'ProfileToken': 'Profile_1',
                'Translation': { 'x': parseFloat(req.body.x), 'y': parseFloat(req.body.y), 'z': parseFloat(req.body.z) },
                'Speed': { 'x': 1, 'y': 1, 'z': 5 }
            };
                                          
            //相对移动，还支持其他方法比如，ContinuousMove 连续移动，连续移动需要停止命令才能停止 和absoluteMove 绝对定位
            device.services.ptz.relativeMove(params2).then((result) => {
                console.log(JSON.stringify(result['data'], null, '  '));
            }).catch((error) => {
                console.error(error);
            });


        })
        .catch(err => {
            console.error('发生错误:', err.message);
        });

    res.send("success");
});


// catch 404 and forward to error handler
app.use(function (req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
    app.use(function (err, req, res, next) {
        res.status(err.status || 500);
        res.render('error', {
            message: err.message,
            error: err
        });
    });
}

app.set('port', process.env.PORT || 3003);
server.listen(3003);
console.log("http  端口3003")



